package com.management.department.teacherinfosystem.Service;

import com.management.department.teacherinfosystem.Entity.*;
import com.management.department.teacherinfosystem.Repository.RoleRepository;
import com.management.department.teacherinfosystem.Repository.UserRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;

/**
 * 用户业务封装 —— 兼容多角色（User ⇄ UserRole ⇄ Role）。
 */
@Service
@RequiredArgsConstructor
@Transactional
public class UserService {

    private final UserRepository userRepo;
    private final RoleRepository roleRepo;
    private final PasswordEncoder encoder;

    /* ============= 查询 ============= */

    public boolean existsByUsername(String username) {
        return userRepo.existsByUsername(username);
    }

    public Optional<User> findByUsername(String username) {
        // 使用带角色预加载的查询方法，避免懒加载问题
        return userRepo.findByUsernameWithRoles(username);
    }

    public Optional<User> findById(Long id) {
        // 使用带角色预加载的查询方法，避免懒加载问题
        return userRepo.findByIdWithRoles(id);
    }

    public Page<User> findAll(Pageable pageable){
        // 使用带角色预加载的分页查询方法，避免懒加载问题
        return userRepo.findAllWithRoles(pageable);
    }

    /* ============= 新增 ============= */

    public User createUser(String username, String rawPassword, String name,
                           String department,
                           String roleCode) {
        if (userRepo.existsByUsername(username)) {
            throw new RuntimeException("用户名已存在");
        }
        Role role = roleRepo.findByName(roleCode)
                .orElseThrow(() -> new RuntimeException("角色不存在: " + roleCode));

        User user = User.builder()
                .username(username)
                .password(encoder.encode(rawPassword))
                .name(name)
                .department(department)
                .userRoles(new HashSet<>())
                .build();

        // 先保存用户以生成 ID
        userRepo.save(user);

        // 绑定角色
        UserRole ur = new UserRole(new UserRoleId(user.getId(), role.getId()), user, role);
        user.getUserRoles().add(ur);

        return user;
    }

    /* ============= 更新 ============= */

    public void updateUser(Long id, String name,
                           String department, String roleCode) {
        User user = userRepo.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));

        if (name != null) user.setName(name);
        if (department != null) user.setDepartment(department);

        if (roleCode != null) {
            Role role = roleRepo.findByName(roleCode)
                    .orElseThrow(() -> new RuntimeException("角色不存在"));
            // 清空旧角色
            user.getUserRoles().clear();
            // 重新绑定新角色
            UserRole ur = new UserRole(new UserRoleId(user.getId(), role.getId()), user, role);
            user.getUserRoles().add(ur);
        }
    }

    /* ============= 删除 ============= */

    public void deleteUser(Long id) {
        userRepo.deleteById(id);
    }

    /* ============= 密码相关 ============= */

    public void changePassword(Long userId, String oldPwd, String newPwd) {
        User user = userRepo.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        if (!encoder.matches(oldPwd, user.getPassword())) {
            throw new RuntimeException("原密码错误");
        }
        user.setPassword(encoder.encode(newPwd));
    }

    public void resetPassword(Long userId, String newPwd) {
        User user = userRepo.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        user.setPassword(encoder.encode(newPwd));
    }
}
